package com.wontube.client.log;

import java.util.Date;

/**
 * @author yuechao
 */
public final class MinLoggerFactory {
	private MinLoggerFactory() {
	}

	private static MinLogger logger = new MinLogger();

	/**
	 * Sets the logger that will write the log messages.
	 */
	public static void setLogger(MinLogger logger) {
		MinLoggerFactory.logger = logger;
	}

	public static MinLogger getLogger(Class<?> clazz) {
		return MinLoggerFactory.logger.getLogger(clazz);
	}

	/**
	 * Performs the actual logging. Default implementation logs to System.out.
	 * Extended and use {@link MinLoggerFactory#logger} set to handle logging differently.
	 */
	public static class MinLogger {
		public static final int LEVEL_ERROR = 5;
		public static final int LEVEL_WARN = 4;
		public static final int LEVEL_INFO = 3;
		public static final int LEVEL_TRACE = 2;
		public static final int LEVEL_DEBUG = 1;
		
		public static int logLevel = MinLogger.LEVEL_ERROR;
		private long firstLogTime = new Date().getTime();

		public boolean isDebugEnabled() {
			return logLevel >= MinLogger.LEVEL_DEBUG;
		}

		public boolean isInfoEnabled() {
			return logLevel >= MinLogger.LEVEL_INFO;
		}

		public boolean isTraceEnabled() {
			return logLevel >= MinLogger. LEVEL_TRACE;
		}

		public boolean isWarnEnabled() {
			return logLevel >= MinLogger.LEVEL_WARN;
		}

		public boolean isErrorEnabled() {
			return logLevel >= MinLogger.LEVEL_ERROR;
		}
		
		public MinLogger getLogger(Class<?> clazz) {
			return this;
		}

		public void error(String message) {
			if (this.isErrorEnabled()) {
				this.log(MinLogger.LEVEL_ERROR, message);
			}
		}

		public void warn(String message) {
			if (this.isWarnEnabled()) {
				this.log(MinLogger.LEVEL_WARN, message);
			}
		}

		public void info(String message) {
			if (this.isInfoEnabled()) {
				this.log(MinLogger.LEVEL_INFO, message);
			}
		}

		public void debug(String message) {
			if (this.isDebugEnabled()) {
				this.log(MinLogger.LEVEL_DEBUG, message);
			}
		}

		public void trace(String message) {
			if (this.isTraceEnabled()) {
				this.log(MinLogger.LEVEL_TRACE, message);
			}
		}

		protected void log(int level, String message) {
			StringBuilder builder = new StringBuilder(256);

			long time = new Date().getTime() - firstLogTime;
			long minutes = time / (1000 * 60);
			long seconds = time / (1000) % 60;
			if (minutes <= 9) {
				builder.append('0');
			}
			builder.append(minutes);
			builder.append(':');
			if (seconds <= 9) {
				builder.append('0');
			}

			builder.append(seconds);

			String category = "";
			switch (level) {
			case MinLogger.LEVEL_DEBUG:
				category = "DEBUG";
				break;
			case MinLogger.LEVEL_TRACE:
				category = "TRACE";
				break;
			case MinLogger.LEVEL_INFO:
				category = "INFO";
				break;
			case MinLogger.LEVEL_WARN:
				category = "WARN";
				break;
			case MinLogger.LEVEL_ERROR:
				category = "ERROR";
				break;
			}
			
			if (!"".equals(category)) {
				builder.append(category);
				builder.append(": ");
			}

			builder.append(message);
			print(builder.toString());
		}

		/**
		 * Prints the message to System.out. Called by the default
		 * implementation of {@link #log(int, String)}.
		 */
		protected void print(String message) {
			System.out.println(message);
		}
	}
}